{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "initial_id",
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    " # !pip install transformers diffusers"
   ]
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "import tensorflow_hub as hub\n",
    "import numpy as np\n",
    "from PIL import Image\n",
    "from tensorflow.keras import mixed_precision\n",
    "\n",
    "# 启用混合精度训练以减少显存占用\n",
    "mixed_precision.set_global_policy('mixed_float16')\n",
    "\n",
    "# 确保 TensorFlow 使用 GPU\n",
    "gpus = tf.config.experimental.list_physical_devices('GPU')\n",
    "\n",
    "if gpus:\n",
    "    try:\n",
    "        # 设置GPU内存增长\n",
    "        for gpu in gpus:\n",
    "            tf.config.experimental.set_memory_growth(gpu, True)\n",
    "    except RuntimeError as e:\n",
    "        print(e)\n",
    "        \n",
    "# 加载 ESRGAN 模型\n",
    "model = hub.load(\"./esrgan-tf2-tensorflow2-esrgan-tf2-v1\")\n",
    "\n",
    "# 加载图像并转换为 NumPy 数组\n",
    "image = Image.open('./9322cc7777230e3032ead7add263974.png').convert(\"RGB\")\n",
    "image = np.array(image)  # 这一步将 PIL 图像转换为 NumPy 数组\n",
    "\n",
    "# 将图像尺寸调整到模型所需的输入尺寸\n",
    "image = tf.image.resize(image, [tf.cast(tf.shape(image)[0] / 4, tf.int32),\n",
    "                                tf.cast(tf.shape(image)[1] / 4, tf.int32)], method=tf.image.ResizeMethod.BILINEAR)\n",
    "                                \n",
    "\n",
    "# 将 NumPy 数组转换为 TensorFlow 张量，并添加批次维度\n",
    "image = tf.convert_to_tensor(image, dtype=tf.float32)\n",
    "image = tf.expand_dims(image, axis=0)\n",
    "\n",
    "# # 模型通常要求输入图像归一化到 [0, 1]\n",
    "# image = image / 255.0\n",
    "\n",
    "# 使用模型生成超分辨率图像\n",
    "upscaled_image = model(image)\n",
    "\n",
    "# 移除批次维度并转换回 NumPy 数组\n",
    "upscaled_image = tf.squeeze(upscaled_image)\n",
    "upscaled_image = tf.clip_by_value(upscaled_image, 0, 255)\n",
    "upscaled_image = tf.cast(upscaled_image, tf.uint8).numpy()\n",
    "\n",
    "# 将张量转换回 PIL 图像\n",
    "upscaled_image_pil = Image.fromarray(upscaled_image)\n",
    "\n",
    "# # 调整图像尺寸到目标分辨率\n",
    "target_size = (2560, 1440)  # 目标分辨率\n",
    "upscaled_image_resized = upscaled_image_pil.resize(target_size, Image.LANCZOS)\n",
    "\n",
    "# 保存调整后的图像\n",
    "upscaled_image_resized.save(\"upscaled_image_resized.png\")\n",
    "# upscaled_image_pil.save(\"upscaled_image_resized.png\")\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-09-02T06:08:33.658139Z",
     "start_time": "2024-09-02T06:08:18.065263Z"
    }
   },
   "id": "467b8ea5d50eb806",
   "execution_count": 2
  },
  {
   "cell_type": "markdown",
   "source": [
    "import tensorflow as tf\n",
    "import tensorflow_hub as hub\n",
    "import numpy as np\n",
    "from PIL import Image\n",
    "\n",
    "# 从 TensorFlow Hub 加载 ESRGAN 模型\n",
    "model = hub.load(\"https://tfhub.dev/captain-pool/esrgan-tf2/1\")\n",
    "\n",
    "# 加载低分辨率图像并调整大小\n",
    "image = Image.open(\"./9322cc7777230e3032ead7add263974.png\").convert(\"RGB\")\n",
    "image = np.array(image)\n",
    "\n",
    "# 将图像尺寸调整到模型所需的输入尺寸\n",
    "image = tf.image.resize(image, [tf.cast(tf.shape(image)[0] / 4, tf.int32),\n",
    "                                tf.cast(tf.shape(image)[1] / 4, tf.int32)])\n",
    "\n",
    "# 将图像转换为 Tensor 并添加批次维度\n",
    "image = tf.convert_to_tensor(image, dtype=tf.float32)\n",
    "image = tf.expand_dims(image, axis=0)\n",
    "\n",
    "# 使用模型生成超分辨率图像\n",
    "upscaled_image = model(image)\n",
    "\n",
    "# 移除批次维度并转换回 numpy 数组\n",
    "upscaled_image = tf.squeeze(upscaled_image)\n",
    "upscaled_image = tf.clip_by_value(upscaled_image, 0, 255)\n",
    "upscaled_image = tf.cast(upscaled_image, tf.uint8).numpy()\n",
    "\n",
    "# 保存或显示结果图像\n",
    "upscaled_image_pil = Image.fromarray(upscaled_image)\n",
    "upscaled_image_pil.save(\"upscaled_image.png\")\n",
    "# upscaled_image_pil.show()\n"
   ],
   "metadata": {
    "collapsed": false
   },
   "id": "94263fac81fa3f2d"
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "import tensorflow_hub as hub\n",
    "import numpy as np\n",
    "from tensorflow.keras import mixed_precision\n",
    "from PIL import Image, ImageEnhance, ImageFilter\n",
    "\n",
    "# 启用混合精度训练以减少显存占用\n",
    "mixed_precision.set_global_policy('mixed_float16')\n",
    "\n",
    "# 确保 TensorFlow 使用 GPU\n",
    "gpus = tf.config.experimental.list_physical_devices('GPU')\n",
    "\n",
    "if gpus:\n",
    "    try:\n",
    "        # 设置GPU内存增长\n",
    "        for gpu in gpus:\n",
    "            tf.config.experimental.set_memory_growth(gpu, True)\n",
    "    except RuntimeError as e:\n",
    "        print(e)\n",
    "\n",
    "# 加载 ESRGAN 模型\n",
    "model = hub.load(\"./esrgan-tf2-tensorflow2-esrgan-tf2-v1\")\n",
    "\n",
    "# 加载图像并转换为 NumPy 数组\n",
    "image = Image.open('./9322cc7777230e3032ead7add263974.png').convert(\"RGB\")\n",
    "image = np.array(image)\n",
    "\n",
    "# 确保图像的高度和宽度可以被 num_splits 整除\n",
    "height, width, _ = image.shape\n",
    "# 修改为合适的分割数\n",
    "num_splits = 4  \n",
    "split_height = height // num_splits\n",
    "split_width = width // num_splits\n",
    "\n",
    "# 对图像进行填充，使其可以被 num_splits 整除\n",
    "def pad_image(image, num_splits):\n",
    "    height, width, _ = image.shape\n",
    "    new_height = (height + num_splits - 1) // num_splits * num_splits\n",
    "    new_width = (width + num_splits - 1) // num_splits * num_splits\n",
    "    padded_image = np.zeros((new_height, new_width, 3), dtype=image.dtype)\n",
    "    padded_image[:height, :width, :] = image\n",
    "    return padded_image\n",
    "\n",
    "# 分割图像\n",
    "def split_image(image, num_splits):\n",
    "    height, width, _ = image.shape\n",
    "    split_height = height // num_splits\n",
    "    split_width = width // num_splits\n",
    "    return [image[y:y + split_height, x:x + split_width]\n",
    "            for x in range(0, width, split_width)\n",
    "            for y in range(0, height, split_height)]\n",
    "\n",
    "def merge_image(images, num_splits):\n",
    "    rows = [np.concatenate(images[i:i + num_splits], axis=1) for i in range(0, len(images), num_splits)]\n",
    "    return np.concatenate(rows, axis=0)\n",
    "\n",
    "# 对图像进行填充\n",
    "padded_image = pad_image(image, num_splits)\n",
    "\n",
    "# 分割图像\n",
    "image_blocks = split_image(padded_image, num_splits)\n",
    "\n",
    "# 放大每个图像块\n",
    "upscaled_blocks = []\n",
    "for block in image_blocks:\n",
    "    block = tf.convert_to_tensor(block, dtype=tf.float32)\n",
    "    block = tf.expand_dims(block, axis=0)  # 添加批次维度\n",
    "    # block = block / 255.0  # 归一化\n",
    "\n",
    "    # 使用模型生成超分辨率图像\n",
    "    upscaled_block = model(block)\n",
    "    \n",
    "    # 移除批次维度并转换回 NumPy 数组\n",
    "    upscaled_block = tf.squeeze(upscaled_block)\n",
    "    # upscaled_block = tf.clip_by_value(upscaled_block, 0, 1)  # 确保值在 [0, 1] 之间\n",
    "    upscaled_block = tf.clip_by_value(upscaled_block, 0, 255)  # 确保值在 [0, 255] 之间\n",
    "    # upscaled_block = (upscaled_block * 255).numpy().astype(np.uint8)  # 转换为 [0, 255] 并转换为 uint8\n",
    "    upscaled_block = tf.cast(upscaled_block, tf.uint8).numpy()  # 转换为 [0, 255] 并转换为 uint8\n",
    "    \n",
    "    upscaled_blocks.append(upscaled_block)\n",
    "\n",
    "# 合并放大的图像块\n",
    "upscaled_image = merge_image(upscaled_blocks, num_splits)\n",
    "\n",
    "# 确保数据类型为 uint8\n",
    "if upscaled_image.dtype != np.uint8:\n",
    "    upscaled_image = upscaled_image.astype(np.uint8)\n",
    "\n",
    "# 确保图像的维度是 (height, width, channels)\n",
    "if len(upscaled_image.shape) == 3 and upscaled_image.shape[2] == 3:\n",
    "    upscaled_image_pil = Image.fromarray(upscaled_image)\n",
    "else:\n",
    "    raise ValueError(\"图像数据的形状不符合 PIL.Image.fromarray 的要求\")\n",
    "\n",
    "# 如果需要，进一步调整图像尺寸到目标分辨率\n",
    "target_size = (2560, 1440)  # 目标分辨率\n",
    "upscaled_image_resized = upscaled_image_pil.resize(target_size, Image.LANCZOS)\n",
    "\n",
    "\n",
    "sharpener = ImageEnhance.Sharpness(upscaled_image_resized)\n",
    "image_pil = sharpener.enhance(2.0)  # 增加锐度\n",
    "\n",
    "# 对比度调整\n",
    "enhancer = ImageEnhance.Contrast(image_pil)\n",
    "# image_pil = enhancer.enhance(1.5)  # 增加对比度\n",
    "\n",
    "# 亮度调整\n",
    "enhancer = ImageEnhance.Brightness(image_pil)\n",
    "# image_pil = enhancer.enhance(1.2) \n",
    "\n",
    "# 保存结果\n",
    "# upscaled_image_resized.save(\"upscaled_image_resized.png\")\n",
    "image_pil.show()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-09-02T07:08:46.681378Z",
     "start_time": "2024-09-02T07:08:21.921575Z"
    }
   },
   "id": "a578e2d72f9678c4",
   "execution_count": 26
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "ename": "NameError",
     "evalue": "name 'ImageEnhance' is not defined",
     "output_type": "error",
     "traceback": [
      "\u001B[1;31m---------------------------------------------------------------------------\u001B[0m",
      "\u001B[1;31mNameError\u001B[0m                                 Traceback (most recent call last)",
      "Cell \u001B[1;32mIn[4], line 2\u001B[0m\n\u001B[0;32m      1\u001B[0m \u001B[38;5;66;03m# 对比度调整\u001B[39;00m\n\u001B[1;32m----> 2\u001B[0m enhancer \u001B[38;5;241m=\u001B[39m \u001B[43mImageEnhance\u001B[49m\u001B[38;5;241m.\u001B[39mContrast(image_pil)\n\u001B[0;32m      3\u001B[0m cc \u001B[38;5;241m=\u001B[39m enhancer\u001B[38;5;241m.\u001B[39menhance(\u001B[38;5;241m1.0\u001B[39m)  \u001B[38;5;66;03m# 增加对比度\u001B[39;00m\n\u001B[0;32m      5\u001B[0m \u001B[38;5;66;03m# 亮度调整\u001B[39;00m\n\u001B[0;32m      6\u001B[0m \u001B[38;5;66;03m# enhancer = ImageEnhance.Brightness(image_pil)\u001B[39;00m\n\u001B[0;32m      7\u001B[0m \u001B[38;5;66;03m# image_pil = enhancer.enhance(1.2) \u001B[39;00m\n\u001B[0;32m      8\u001B[0m \n\u001B[0;32m      9\u001B[0m \u001B[38;5;66;03m# 保存结果\u001B[39;00m\n\u001B[0;32m     10\u001B[0m \u001B[38;5;66;03m# upscaled_image_resized.save(\"upscaled_image_resized.png\")\u001B[39;00m\n",
      "\u001B[1;31mNameError\u001B[0m: name 'ImageEnhance' is not defined"
     ]
    }
   ],
   "source": [
    "# 对比度调整\n",
    "enhancer = ImageEnhance.Contrast(image_pil)\n",
    "cc = enhancer.enhance(1.0)  # 增加对比度\n",
    "\n",
    "# 亮度调整\n",
    "# enhancer = ImageEnhance.Brightness(image_pil)\n",
    "# image_pil = enhancer.enhance(1.2) \n",
    "\n",
    "# 保存结果\n",
    "# upscaled_image_resized.save(\"upscaled_image_resized.png\")\n",
    "cc.show()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-08-30T06:47:28.558391Z",
     "start_time": "2024-08-30T06:47:28.509628Z"
    }
   },
   "id": "c1da549a627d4ced",
   "execution_count": 4
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "import cv2\n",
    "import numpy as np\n",
    "\n",
    "# 将 PIL 图像转换为 NumPy 数组\n",
    "image_array = np.array(cc)\n",
    "\n",
    "# 使用 OpenCV 进行去噪\n",
    "denoised_image = cv2.fastNlMeansDenoisingColored(image_array, None, 10, 10, 7, 21)\n",
    "\n",
    "# 转换回 PIL 图像\n",
    "final_image = Image.fromarray(denoised_image)\n",
    "final_image.show()\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-08-30T05:32:48.794246Z",
     "start_time": "2024-08-30T05:32:45.296839Z"
    }
   },
   "id": "a7b7fdada5855549",
   "execution_count": 62
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "import tensorflow_hub as hub\n",
    "import numpy as np\n",
    "from tensorflow.keras import mixed_precision\n",
    "from PIL import Image, ImageEnhance\n",
    "\n",
    "# 启用混合精度训练以减少显存占用\n",
    "mixed_precision.set_global_policy('mixed_float16')\n",
    "\n",
    "# 确保 TensorFlow 使用 GPU\n",
    "gpus = tf.config.experimental.list_physical_devices('GPU')\n",
    "\n",
    "if gpus:\n",
    "    try:\n",
    "        for gpu in gpus:\n",
    "            tf.config.experimental.set_memory_growth(gpu, True)\n",
    "    except RuntimeError as e:\n",
    "        print(e)\n",
    "\n",
    "# 加载 ESRGAN 模型\n",
    "model = hub.load(\"./esrgan-tf2-tensorflow2-esrgan-tf2-v1\")\n",
    "\n",
    "# 加载图像并转换为 NumPy 数组\n",
    "image = Image.open('./9322cc7777230e3032ead7add263974.png').convert(\"RGB\")\n",
    "image = np.array(image)\n",
    "\n",
    "# 确保图像的高度和宽度可以被 num_splits 整除\n",
    "height, width, _ = image.shape\n",
    "num_splits = 4  # 修改为合适的分割数\n",
    "split_height = height // num_splits\n",
    "split_width = width // num_splits\n",
    "\n",
    "# 对图像进行填充，使其可以被 num_splits 整除\n",
    "def pad_image(image, num_splits):\n",
    "    height, width, _ = image.shape\n",
    "    new_height = (height + num_splits - 1) // num_splits * num_splits\n",
    "    new_width = (width + num_splits - 1) // num_splits * num_splits\n",
    "    padded_image = np.zeros((new_height, new_width, 3), dtype=image.dtype)\n",
    "    padded_image[:height, :width, :] = image\n",
    "    return padded_image\n",
    "\n",
    "# 分割图像并保留每块的位置\n",
    "def split_image(image, split_height, split_width):\n",
    "    height, width, _ = image.shape\n",
    "    blocks = []\n",
    "    for y in range(0, height, split_height):\n",
    "        for x in range(0, width, split_width):\n",
    "            block = image[y:y + split_height, x:x + split_width]\n",
    "            blocks.append((x, y, block))  # 保留位置索引\n",
    "    return blocks\n",
    "\n",
    "# 合并图像，确保按正确顺序排列\n",
    "def merge_image(blocks, original_image_shape, scale_factor):\n",
    "    original_height, original_width, _ = original_image_shape\n",
    "    \n",
    "    # 计算放大后的图像大小\n",
    "    upscaled_height = original_height * scale_factor\n",
    "    upscaled_width = original_width * scale_factor\n",
    "    \n",
    "    # 创建一个空白的图像，用于合并所有块\n",
    "    merged_image = np.zeros((upscaled_height, upscaled_width, 3), dtype=np.uint8)\n",
    "    \n",
    "    for (x, y, block) in blocks:\n",
    "        block_height, block_width, _ = block.shape\n",
    "        \n",
    "        # 将块放回它们在合并图像中的原始位置\n",
    "        upscaled_x = x * scale_factor\n",
    "        upscaled_y = y * scale_factor\n",
    "        \n",
    "        # 在合并图像中填充块\n",
    "        merged_image[upscaled_y:upscaled_y + block_height, upscaled_x:upscaled_x + block_width] = block\n",
    "    \n",
    "    return merged_image\n",
    "\n",
    "\n",
    "# 对图像进行填充\n",
    "padded_image = pad_image(image, num_splits)\n",
    "\n",
    "# 分割图像\n",
    "image_blocks = split_image(padded_image, split_height, split_width)\n",
    "\n",
    "# 放大每个图像块\n",
    "upscaled_blocks = []\n",
    "for x, y, block in image_blocks:\n",
    "    block = tf.convert_to_tensor(block, dtype=tf.float32)\n",
    "    block = tf.expand_dims(block, axis=0)  # 添加批次维度\n",
    "    \n",
    "    # 使用模型生成超分辨率图像\n",
    "    upscaled_block = model(block)\n",
    "    \n",
    "    # 移除批次维度并转换回 NumPy 数组\n",
    "    upscaled_block = tf.squeeze(upscaled_block)\n",
    "    upscaled_block = tf.clip_by_value(upscaled_block, 0, 255)\n",
    "    upscaled_block = tf.cast(upscaled_block, tf.uint8).numpy()  # 转换为 uint8\n",
    "    \n",
    "    upscaled_blocks.append((x, y, upscaled_block))  # 保留原始位置\n",
    "\n",
    "# 合并放大的图像块\n",
    "upscaled_image = merge_image(upscaled_blocks, padded_image.shape,4)\n",
    "\n",
    "# 确保数据类型为 uint8\n",
    "if upscaled_image.dtype != np.uint8:\n",
    "    upscaled_image = upscaled_image.astype(np.uint8)\n",
    "\n",
    "# 转换为 PIL 图像\n",
    "upscaled_image_pil = Image.fromarray(upscaled_image)\n",
    "\n",
    "# 如果需要，进一步调整图像尺寸到目标分辨率\n",
    "target_size = (2560, 1440)  # 目标分辨率\n",
    "upscaled_image_resized = upscaled_image_pil.resize(target_size, Image.LANCZOS)\n",
    "\n",
    "# 增加锐度\n",
    "sharpener = ImageEnhance.Sharpness(upscaled_image_resized)\n",
    "image_pil = sharpener.enhance(2.0)\n",
    "\n",
    "# 对比度调整\n",
    "enhancer = ImageEnhance.Contrast(image_pil)\n",
    "# image_pil = enhancer.enhance(1.5)\n",
    "\n",
    "# 亮度调整\n",
    "enhancer = ImageEnhance.Brightness(image_pil)\n",
    "# image_pil = enhancer.enhance(1.2)\n",
    "\n",
    "# 显示结果\n",
    "# image_pil.show()\n",
    "# 保存结果\n",
    "image_pil.save(\"upscaled_image_resized.png\")"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-09-02T07:31:04.232752Z",
     "start_time": "2024-09-02T07:30:40.664096Z"
    }
   },
   "id": "7e709af0f64b9c58",
   "execution_count": 34
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "height, width = upscaled_blocks[0][2].shape\n",
    "rows = []\n",
    "for i in range(0, len(upscaled_blocks), num_splits):\n",
    "    row_blocks = [b[2] for b in upscaled_blocks[i:i + num_splits]]\n",
    "    rows.append(np.concatenate(row_blocks, axis=1))\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-08-30T04:41:15.988554Z",
     "start_time": "2024-08-30T04:41:15.976964Z"
    }
   },
   "id": "a5957290ecbea4cd",
   "execution_count": 33
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Available devices: [PhysicalDevice(name='/physical_device:CPU:0', device_type='CPU'), PhysicalDevice(name='/physical_device:GPU:0', device_type='GPU')]\n",
      "TensorFlow is using GPU\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "\n",
    "# 打印 TensorFlow 可用的物理设备\n",
    "print(\"Available devices:\", tf.config.experimental.list_physical_devices())\n",
    "\n",
    "# 检查 TensorFlow 是否使用 GPU\n",
    "if tf.config.experimental.list_physical_devices('GPU'):\n",
    "    print(\"TensorFlow is using GPU\")\n",
    "else:\n",
    "    print(\"TensorFlow is using CPU\")\n"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-08-30T03:28:47.061303Z",
     "start_time": "2024-08-30T03:28:47.042304Z"
    }
   },
   "id": "6312721d2563bced",
   "execution_count": 13
  },
  {
   "cell_type": "code",
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Num GPUs Available:  1\n"
     ]
    }
   ],
   "source": [
    "\n",
    "import tensorflow as tf\n",
    "\n",
    "print(\"Num GPUs Available: \", len(tf.config.experimental.list_physical_devices('GPU')))"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-09-02T06:59:55.473785Z",
     "start_time": "2024-09-02T06:59:55.467706Z"
    }
   },
   "id": "533f0bd7dfd77b87",
   "execution_count": 17
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [
    "# 清理 GPU 内存\n",
    "tf.keras.backend.clear_session()"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2024-09-02T07:00:00.195495Z",
     "start_time": "2024-09-02T07:00:00.148052Z"
    }
   },
   "id": "356b53c47c8792eb",
   "execution_count": 18
  },
  {
   "cell_type": "code",
   "outputs": [],
   "source": [],
   "metadata": {
    "collapsed": false
   },
   "id": "60c11830a93673f3"
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
